package com.happyelements.display
{
	import com.happyelements.display.rendering.IRenderer;
	
	import flash.display.BitmapData;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	/**
	 *
	 * @author Steven
	 *
	 */
	public class HEDisplayObject
	{
		private static const __ZERO_POINT:Point = new Point();
		
		public var x:Number = 0;
		
		public var y:Number = 0;
		
		protected var renderer:IRenderer;
		
		private var _parent:HEDisplayObjectContainer;
		
		private var _scale:Number = 1.0;
		
		private var _alpha:Number = 1.0;
		
		public function update(canvas:BitmapData, rect:Rectangle):void
		{
			if (this.renderer)
			{
				var point:Point = new Point(this.x, this.y);
				point = parent.localToGlobal(point);			//parent一定存在，否则update不会被调用
					
				renderer.paint(canvas, rect, point.x, point.y);
				
				afterUpdate();
			}
		}
		
		public function get width():Number
		{
			return getAnimationWidth();
		}
		
		public function get height():Number
		{
			return getAnimationHeight();
		}
		
		public final function get scale():Number
		{
			return this._scale;
		}
		
		public final function set scale(value:Number):void
		{
			this._scale = value;
			
			refreshScale();
		}
		
		public final function get alpha():Number
		{
			return this._alpha;
		}
		
		public final function set alpha(value:Number):void
		{
			this._alpha = value;
			
			refreshAlpha();
		}
		
		public final function get parent():HEDisplayObjectContainer
		{
			return this._parent;
		}
		
		public function globalToLocal(point:Point):Point
		{
			var result:Point = parent.globalToLocal(point);
			
			result.offset(- this.x, - this.y);
			
			return result;
		}
		
		public function localToGlobal(point:Point):Point
		{
			var result:Point = point.clone();
			
			result.offset(this.x, this.y);
			
			return parent.localToGlobal(result);
		}
		
		public function getRect(targetCoordinateSpace:HEDisplayObject = null):Rectangle
		{
			var offset:Point = this.renderer ? renderer.currentOriginOffset : null;
			offset || (offset = __ZERO_POINT);
			
			if (targetCoordinateSpace && targetCoordinateSpace !== this)
			{
				offset = localToGlobal(offset);
				offset = targetCoordinateSpace.globalToLocal(offset);
			}
			
			return new Rectangle(offset.x, offset.y, getAnimationWidth(), getAnimationHeight());
		}
		
		public function hitTestPoint(x:Number, y:Number, shapeFlag:Boolean = false):Boolean
		{
			var point:Point = globalToLocal(new Point(x, y));
			
			if (shapeFlag)
			{
				return this.renderer && renderer.hitTest(point.x, point.y);
			}
			else
			{
				return getRect().containsPoint(point);
			}
		}
		
		public final function moveTo(x:Number, y:Number):void
		{
			this.x = x;
			this.y = y;
		}
		
		protected function afterUpdate():void
		{
			
		}
		
		internal function refreshScale():void
		{
			this.renderer && (renderer.scale = getGlobalScale());
		}
		
		internal function refreshAlpha():void
		{
			this.renderer && (renderer.alpha = getGlobalAlpha());
		}
		
		internal final function refreshParent(parent:HEDisplayObjectContainer):void
		{
			this._parent = parent;
			
			refreshScale();
			refreshAlpha();
		}
		
		internal final function getGlobalScale():Number
		{
			var result:Number = this._scale;
			var interator:HEDisplayObject = this;
			
			while (interator.parent)
			{
				interator = interator.parent;
				result *= interator._scale;
			}
			
			return result;
		}
		
		internal final function getGlobalAlpha():Number
		{
			var result:Number = this._alpha;
			var interator:HEDisplayObject = this;
			
			while (interator.parent)
			{
				interator = interator.parent;
				result *= interator._alpha;
			}
			
			return result;
		}
		
		private function getAnimationWidth():Number
		{
			return this.renderer ? renderer.currentWidth : 0;
		}
		
		private function getAnimationHeight():Number
		{
			return this.renderer ? renderer.currentHeight : 0;
		}
	}
}